﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Dynamic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using ContractManager.BLL.Business;
using ContractManager.Common.Class;
using ContractManager.Common.FormBase;
using ContractManager.Entity;
using DevExpress.Utils;
using DevExpress.XtraBars;
using DevExpress.XtraEditors;
using DevExpress.XtraEditors.Controls;
using DevExpress.XtraEditors.Repository;
using DevExpress.XtraGrid;
using DevExpress.XtraGrid.Views.Base;
using DevExpress.XtraGrid.Views.Grid;
using DevExpress.XtraLayout;
using DevExpress.XtraLayout.Utils;

namespace ContractManager.Lists.Forms
{
    public partial class FrmDynamicBase : XtraFormBase
    {
        #region "Private Variable"

        private readonly List<string> _listFieldLookupHasEvent = new List<string>();
        private readonly List<string> _listFieldNumberHasEvent = new List<string>();
        private readonly List<string> _listFieldWhere = new List<string>();
        private readonly CustomValidation _myvalidation = new CustomValidation();
        
        public List<GridControl> ListGridControl = new List<GridControl>();
        public List<RepositoryItemSearchLookUpEdit> ListSearchLookupEdit = new List<RepositoryItemSearchLookUpEdit>();

        public int GridNo;
        public int MasterId;
        public bool OnlyView;
        public bool SaveClose;
        public bool SaveNew;

        private LayoutControlItem _lastItem;
        private List<FieldTables> _list;
        private List<FieldTables> _listGrid;
        public string KeyFieldName { get; set; }
        public string GetByMasterSql { get; set; }
        public string DeleteByMasterSql { get; set; }
        public string ControlName { get; set; }
        public string DisplayMember { get; set; }
        public string ValueMember { get; set; }

        public int SourceDataId { get; set; }

        private LayoutControlItem LastItem
        {
            get { return _lastItem; }
        }

        #endregion

        #region "Form Construction"

        public FrmDynamicBase()
        {
            InitializeComponent();
        }

        #endregion

        #region "Private Method"

        /// <summary>
        /// Blank Form
        /// </summary>
        private void BlankForm()
        {
            ResetControls();
        }

        /// <summary>
        /// Create Layout on Form
        /// </summary>
        private void CreateLayoutForms()
        {
            _list = ClsFieldTables.SelectByForm(FormNo);
            _listGrid = _list.Where(e => e.FieldTalbeType == 6).ToList();
            CreateControlDynamic(_list);
        }

        /// <summary>
        ///     Create new control dynamic on form
        /// </summary>
        /// <param name="list">list Field on form</param>
        private void CreateControlDynamic(List<FieldTables> list)
        {
            var listGrid = new List<GridView>();
            layoutControl.BeginUpdate();
            foreach (FieldTables field in list)
            {
                string controlName = field.FieldTableName;
                string controlDisplay = field.FieldTableDescription;
                string controlGridLayout = field.GridLayoutName;
                string displayMember = field.DisplayMember;
                string valueMember = field.ValueMember;
                
                int typeId = Convert.ToInt32(field.FieldTalbeType);
                var item = new LayoutControlItem {Text = controlDisplay};
                switch (typeId)
                {
                    #region "1. TextEdit"
                    case 1: //TextEdit
                        var txtTextEdit = new TextEdit {Name = controlName};
                        txtTextEdit.Properties.ReadOnly = Convert.ToBoolean(field.FieldTableReadOnly);
                        txtTextEdit.TabStop = !Convert.ToBoolean(field.FieldTableIsTabStop);
                        layoutControl.AddItem(item, LastItem, InsertType.Bottom);
                        item.Control = txtTextEdit;
                        _lastItem = item;
                        item.Name = "item" + controlName;
                        item.Height = 25;
                        if (field.FieldHasEvents == true)
                        {
                            txtTextEdit.EditValueChanged += txtTextEdit_EditValueChanged;
                        }
                        break;
                    #endregion

                    #region "2.MemoEdit Control"
                    case 2: //Memo Edit
                        var txtMemoEdit = new MemoEdit {Name = controlName};
                        txtMemoEdit.Properties.ReadOnly = Convert.ToBoolean(field.FieldTableReadOnly);
                        txtMemoEdit.TabStop = !Convert.ToBoolean(field.FieldTableIsTabStop);
                        layoutControl.AddItem(item, LastItem, InsertType.Bottom);
                        item.Control = txtMemoEdit;
                        _lastItem = item;
                        item.Name = "item" + controlName;
                        item.Height = 25;
                        break;
                    #endregion

                    #region "3.CalcEdit"
                    case 3: //CalcEdit
                        var txtCalcEdit = new CalcEdit {Name = controlName};
                        txtCalcEdit.Properties.ReadOnly = Convert.ToBoolean(field.FieldTableReadOnly);
                        txtCalcEdit.TabStop = !Convert.ToBoolean(field.FieldTableIsTabStop);
                        txtCalcEdit.Properties.Mask.EditMask = @"n0";
                        txtCalcEdit.Properties.Mask.UseMaskAsDisplayFormat = true;
                        txtCalcEdit.StyleController = layoutControl;
                        layoutControl.AddItem(item, LastItem, InsertType.Bottom);
                        item.Control = txtCalcEdit;
                        _lastItem = item;
                        item.Name = "item" + controlName;
                        item.Height = 25;
                        if (field.FieldHasEvents == true)
                        {
                            txtCalcEdit.EditValueChanged += txtCalcEdit_EditValueChanged;
                        }
                        break;
                    #endregion

                    #region "4.DateEdit"
                    case 4: //DateTime
                        var txtDateEdit = new DateEdit {Name = controlName};
                        txtDateEdit.Properties.ReadOnly = Convert.ToBoolean(field.FieldTableReadOnly);
                        txtDateEdit.TabStop = !Convert.ToBoolean(field.FieldTableIsTabStop);
                        txtDateEdit.Properties.CalendarTimeProperties.CloseUpKey = new KeyShortcut(Keys.F4);
                        txtDateEdit.Properties.Mask.EditMask = @"dd/MM/yyyy";
                        txtDateEdit.Properties.Mask.UseMaskAsDisplayFormat = true;
                        txtDateEdit.StyleController = layoutControl;
                        layoutControl.AddItem(item, LastItem, InsertType.Bottom);
                        item.Control = txtDateEdit;
                        _lastItem = item;
                        item.Name = "item" + controlName;
                        item.Height = 25;
                        break;
                    #endregion

                    #region "7.PictureEdit"
                    case 7: //PictureEdit
                        var txtPictureEdit = new PictureEdit {Name = controlName};
                        txtPictureEdit.Properties.ReadOnly = Convert.ToBoolean(field.FieldTableReadOnly);
                        txtPictureEdit.TabStop = !Convert.ToBoolean(field.FieldTableIsTabStop);
                        txtPictureEdit.Properties.PictureStoreMode = PictureStoreMode.ByteArray;
                        layoutControl.AddItem(item, LastItem, InsertType.Bottom);
                        item.Control = txtPictureEdit;
                        _lastItem = item;
                        item.Name = "item" + controlName;
                        item.Height = 25;
                        break;
                    #endregion

                    #region "8.CheckEdit"
                    case 8: //CheckEdit
                        var txtCheckEdit = new CheckEdit {Name = controlName};
                        txtCheckEdit.Properties.ReadOnly = Convert.ToBoolean(field.FieldTableReadOnly);
                        txtCheckEdit.TabStop = !Convert.ToBoolean(field.FieldTableIsTabStop);
                        txtCheckEdit.Text = controlDisplay;
                        layoutControl.AddItem(item, LastItem, InsertType.Bottom);
                        item.Control = txtCheckEdit;
                        _lastItem = item;
                        item.Name = "item" + controlName;
                        item.Height = 25;
                        break;
                    #endregion

                    #region "9.ComboEdit"
                    case 9: //ComboEdit
                        var txtComboEdit = new ComboBoxEdit {Name = controlName};
                        txtComboEdit.Properties.ReadOnly = Convert.ToBoolean(field.FieldTableReadOnly);
                        txtComboEdit.TabStop = !Convert.ToBoolean(field.FieldTableIsTabStop);
                        string[] arrValue = String.Format("{0}", field.ValueMember).Split(',');
                        foreach (string s in arrValue)
                        {
                            txtComboEdit.Properties.Items.Add(s);
                        }
                        layoutControl.AddItem(item, LastItem, InsertType.Bottom);
                        item.Control = txtComboEdit;
                        _lastItem = item;
                        item.Name = "item" + controlName;
                        item.Height = 25;
                        break;
                    #endregion

                    #region "10.LookupEdit"
                    case 10: //Lookup Edit
                        DataTable dvLookupEdit = ClsSourceData.GetControlDataBySourceId(field.SourceDataId, "");
                        var slupLookupEdit = new LookUpEdit { Name = controlName };
                        slupLookupEdit.Properties.TextEditStyle=TextEditStyles.Standard;
                        slupLookupEdit.Properties.DataSource = new BindingSource(dvLookupEdit, "");
                        slupLookupEdit.Properties.DisplayMember = displayMember;
                        slupLookupEdit.Properties.ValueMember = valueMember;
                        slupLookupEdit.Properties.NullText = "";
                        slupLookupEdit.Tag = field;
                        LookUpColumnInfoCollection coll = slupLookupEdit.Properties.Columns;
                        var slistField = field.GridLayoutFieldWith.Split(',');
                        var sCaptionField = field.FieldTableListLookupChange.Split(',');
                        for (int index = 0; index < slistField.Length; index++)
                        {
                            var sField = slistField[index];
                            coll.Add(new LookUpColumnInfo(sField,0, sCaptionField[index]));
                        }
                        slupLookupEdit.Properties.BestFitMode = BestFitMode.BestFitResizePopup;
                        slupLookupEdit.Properties.SearchMode = SearchMode.AutoFilter;
                        layoutControl.AddItem(item, LastItem, InsertType.Bottom);
                        item.Control = slupLookupEdit;
                        _lastItem = item;
                        item.Name = "item" + controlName;
                        item.Height = 25;
                        if (field.FieldHasEvents == true)
                        {
                            slupLookupEdit.EditValueChanged += slupDropDown_EditValueChanged;
                        }
                        if (field.FieldTableAddButton==true)
                        {
                            slupLookupEdit.Properties.Buttons.Add(
                                new EditorButton(
                                    DevExpress.XtraEditors.Controls.ButtonPredefines.Plus, "btnAdd", -1, true, true,
                                    false, ImageLocation.MiddleCenter, null,
                                    new KeyShortcut(Keys.F3)));
                            slupLookupEdit.ButtonClick+=SlupLookupEditOnButtonClick;
                        }
                        break;
                    #endregion

                    #region "5.Search LookupEdit"
                    case 5: //Lookup Edit
                        DataTable dvDropDown = ClsSourceData.GetControlDataBySourceId(field.SourceDataId, "");
                        var slupDropDown = new SearchLookUpEdit {Name = controlName};
                        slupDropDown.Tag = field;
                        slupDropDown.Properties.ReadOnly = Convert.ToBoolean(field.FieldTableReadOnly);
                        slupDropDown.TabStop = !Convert.ToBoolean(field.FieldTableIsTabStop);
                        slupDropDown.Properties.View.OptionsBehavior.AutoPopulateColumns = false;
                        slupDropDown.Properties.View.OptionsView.ColumnAutoWidth = false;
                        slupDropDown.Properties.DataSource = null;
                        slupDropDown.Properties.DataSource = dvDropDown;
                        slupDropDown.Properties.DisplayMember = displayMember;
                        slupDropDown.Properties.ValueMember = valueMember;
                        slupDropDown.Properties.NullText = "";
                        slupDropDown.Properties.PopupFormWidth = 350;
                        layoutControl.AddItem(item, LastItem, InsertType.Bottom);
                        
                        item.Control = slupDropDown;
                        _lastItem = item;
                        item.Name = "item" + controlName;
                        item.Height = 25;
                        if (!String.IsNullOrEmpty(controlGridLayout))
                        {
                            string fileLayout = ClsVariable.GetRestoreLayoutFullPath(controlGridLayout);
                            slupDropDown.Properties.View.RestoreLayoutFromXml(fileLayout, OptionsLayoutBase.FullLayout);
                        }
                        if (field.FieldHasEvents == true)
                        {
                            slupDropDown.EditValueChanged += slupDropDown_EditValueChanged;
                        }
                        slupDropDown.ForceInitialize();
                        break;
                    #endregion

                    #region "6.GridControl"
                    case 6: //Grid
                        string source = ClsSourceData.SelectByPk(Convert.ToInt32(field.SourceDataId)).SourceDataValue;
                        string sql = String.Format("{0} WHERE {1}={2}", source,
                            Form_TableKeyField, MasterId);
                        DataTable dvGrid = ClsSourceData.GetGridDataBySourceId(sql, "");
                        var grdDynamic = new GridControl {Name = controlName, UseEmbeddedNavigator = true};
                        var gridStatusGridView = new GridView();
                        gridStatusGridView.Tag = field;
                        grdDynamic.MainView = gridStatusGridView;
                        gridStatusGridView.Name = "grv" + controlName;
                        gridStatusGridView.GridControl = grdDynamic;
                        grdDynamic.ViewCollection.AddRange(new BaseView[]{gridStatusGridView});

                        layoutControl.AddItem(item, LastItem, InsertType.Bottom);
                        item.Control = grdDynamic;
                        _lastItem = item;
                        item.Name = "item" + controlName;
                        item.Height = 50;

                        #region "Add RepositoryItem"

                        //Add control Calc percent
                        //var repositoryItemPercentCalcEdit = new RepositoryItemCalcEdit();
                        //repositoryItemPercentCalcEdit.AutoHeight = false;
                        //repositoryItemPercentCalcEdit.Mask.EditMask = @"p";
                        //repositoryItemPercentCalcEdit.Mask.UseMaskAsDisplayFormat = true;
                        //repositoryItemPercentCalcEdit.Name = "repositoryItemPercentCalcEdit1";

                        ////Add control Calc Number
                        //var repositoryItemNumberCalcEdit = new RepositoryItemCalcEdit();
                        //repositoryItemNumberCalcEdit.AutoHeight = false;

                        //repositoryItemNumberCalcEdit.Mask.EditMask = @"n0";
                        //repositoryItemNumberCalcEdit.Mask.UseMaskAsDisplayFormat = true;
                        //repositoryItemNumberCalcEdit.Name = "repositoryItemNumberCalcEdit1";
                        ////Add control Date Number
                        //var repositoryItemDateEdit = new RepositoryItemDateEdit();
                        //repositoryItemDateEdit.AutoHeight = false;

                        //repositoryItemDateEdit.CalendarTimeProperties.CloseUpKey = new KeyShortcut(Keys.F4);
                        //repositoryItemDateEdit.CalendarTimeProperties.PopupBorderStyle = PopupBorderStyles.Default;
                        //repositoryItemDateEdit.Mask.EditMask = @"dd/MM/yyyy";
                        //repositoryItemDateEdit.Mask.UseMaskAsDisplayFormat = true;
                        //repositoryItemDateEdit.Name = "repositoryItemDateEdit";
                        //Add control Memo Edit RepositoryItemMemoEdit
                        var repositoryItemMemoEdit = new RepositoryItemMemoEdit();
                        repositoryItemMemoEdit.Name = "RepositoryItemMemoEdit";

                        #endregion

                        #region "Add Control to Grid"

                        //grdDynamic.RepositoryItems.Add(repositoryItemPercentCalcEdit);
                        //grdDynamic.RepositoryItems.Add(repositoryItemNumberCalcEdit);
                        //grdDynamic.RepositoryItems.Add(repositoryItemDateEdit);
                        grdDynamic.RepositoryItems.Add(repositoryItemMemoEdit);

                        #endregion

                        #region "Get list control Lookup for Grid form Data Source (Type Search Lookup Edit)"

                        List<FieldTableDetails> listDetails = ClsFieldTables.SelectDetails(field.FieldTableId);

                        #region "Search Lookup Edit"
                        var listSearchLookup = listDetails.Where(p => p.FieldTableType == 6).ToList();
                        foreach (FieldTableDetails detail in listSearchLookup)
                        {
                            var repositoryItemSearchLookUpEdit = new RepositoryItemSearchLookUpEdit
                            {
                                Name = String.Format("RepositoryItemSearchLookUpEdit{0}{1}",
                                    field.FieldTableName, detail.FieldTableDetailColumnName),
                                AutoHeight = false
                            };

                            string where = detail.FieldTableDetailHasEvent == true ? " WHERE 1=0" : "";
                            DataTable dvLookup = ClsSourceData.GetControlDataBySourceId(detail.SourceDataId, where);
                            repositoryItemSearchLookUpEdit.DataSource = dvLookup;
                            repositoryItemSearchLookUpEdit.DisplayMember = detail.DisplayMember;
                            repositoryItemSearchLookUpEdit.ValueMember = detail.ValueMember;
                            repositoryItemSearchLookUpEdit.NullText = "";
                            var repositoryItemSearchLookUpGridView = new GridView
                            {
                                FocusRectStyle = DrawFocusRectStyle.RowFocus,
                                Name = String.Format("RepositoryItemSearchLookUpGridView{0}{1}", field.FieldTableName, detail.FieldTableDetailColumnName)
                            };
                            if (!String.IsNullOrEmpty(detail.FieldTableLayout))
                            {
                                string fileLayout = ClsVariable.GetRestoreLayoutFullPath(detail.FieldTableLayout);
                                repositoryItemSearchLookUpGridView.RestoreLayoutFromXml(fileLayout,
                                    OptionsLayoutBase.FullLayout);
                            }
                            repositoryItemSearchLookUpEdit.View = repositoryItemSearchLookUpGridView;
                            

                            grdDynamic.RepositoryItems.Add(repositoryItemSearchLookUpEdit);
                            ListSearchLookupEdit.Add(repositoryItemSearchLookUpEdit);
                        }
                        #endregion

                        #region "Lookup Edit"
                        var listLookupEdit = listDetails.Where(p => p.FieldTableType == 10).ToList();
                        foreach (FieldTableDetails detail in listLookupEdit)
                        {
                            var repositoryItemLookUpEdit = new RepositoryItemLookUpEdit
                            {
                                Name = String.Format("RepositoryItemLookUpEdit{0}{1}",
                                    field.FieldTableName, detail.FieldTableDetailColumnName),
                                AutoHeight = false
                            };

                            string where = detail.FieldTableDetailHasEvent == true ? " WHERE 1=0" : "";
                            DataTable dvLookup = ClsSourceData.GetControlDataBySourceId(detail.SourceDataId, where);
                            repositoryItemLookUpEdit.DataSource = new BindingSource(dvLookup, "");// dvLookup;
                            repositoryItemLookUpEdit.DisplayMember = detail.DisplayMember;
                            repositoryItemLookUpEdit.ValueMember = detail.ValueMember;
                            repositoryItemLookUpEdit.NullText = "";


                            LookUpColumnInfoCollection repositoryCols = repositoryItemLookUpEdit.Columns;
                            var rlistField = detail.FieldTableListField.Split(',');
                            var rCaptionField = detail.FieldTableListCaption.Split(',');
                            for (int index = 0; index < rlistField.Length; index++)
                            {
                                var sField = rlistField[index];
                                repositoryCols.Add(new LookUpColumnInfo(sField, 0, rCaptionField[index]));
                            }
                            repositoryItemLookUpEdit.BestFitMode = BestFitMode.BestFitResizePopup;
                            repositoryItemLookUpEdit.SearchMode = SearchMode.AutoFilter;

                            grdDynamic.RepositoryItems.Add(repositoryItemLookUpEdit);
                        }
                        #endregion

                        #endregion

                        #region "Load layout to Grid View"

                        if (!String.IsNullOrEmpty(controlGridLayout))
                        {
                            string fileLayout = ClsVariable.GetRestoreLayoutFullPath(controlGridLayout);
                            gridStatusGridView.RestoreLayoutFromXml(fileLayout, OptionsLayoutBase.FullLayout);
                        }

                        grdDynamic.DataSource = dvGrid;

                        #endregion

                        #region "Check control has event value change"

                        if (field.FieldHasEvents == true)
                        {
                            gridStatusGridView.CellValueChanged += gridStatusGridView_CellValueChanged;
                        }

                        #endregion

                        listGrid.Add(gridStatusGridView);
                        ListGridControl.Add(grdDynamic);
                        grdDynamic.ForceInitialize();
                        //grdDynamic.Dispose();
                        break;
                    #endregion
                }
            }

            layoutControl.BestFit();
            layoutControl.EndUpdate();
        }

        private void SlupLookupEditOnButtonClick(object sender, ButtonPressedEventArgs e)
        {
            if (e.Button.Caption.Equals("btnAdd"))
            {
                var lookupEdit = sender as LookUpEdit;
                if (lookupEdit == null) return;
                var firstList = _list.FirstOrDefault(p => p.FieldTableName == lookupEdit.Name);
                if (firstList == null) return;
                int formNo = Convert.ToInt32(firstList.FieldTableFormNo);
                var form = ClsForms.SelectByPk(formNo);
                var frm = new FrmDynamicBase
                {
                    MasterId = 0,
                    AsSysBillStyleId = Convert.ToInt32(form.Form_SysBillStyleId),
                    AsSysMyCoYearId = ClsVariable.AsSysMyCoYearId,
                    AsPerPersonId = ClsVariable.EmployeeId,
                    FormNo = formNo,
                    FormSysBillStyleIdExport = Convert.ToInt32(form.Form_SysBillStyleIdExport),
                    FormXtraLayoutTemplate = form.Form_XtraLayoutTemplate,
                    FormXtraGridLayoutTemplate = form.Form_XtraGridLayoutTemplate,
                    FormReportLayoutTemplate = form.Form_ReportLayoutTemplate,
                    FormDetailVatGridLayout = form.Form_DetailVatGridLayout,
                    VoucherCate = Convert.ToInt32(form.VoucherCate),
                    IsPrintAfterSave = Convert.ToBoolean(form.Form_IsPrintAfterSave),
                    FormAccountDefault = Convert.ToInt32(form.FormAccountDefault),
                    FormIsNotValidate = Convert.ToBoolean(form.FormIsNotValidate),

                    TableName = form.Form_TableName,
                    Form_TableKeyField = form.Form_TableKeyField,
                    Form_SourceSql = form.Form_SourceSql,
                    Form_Detail_SqlDeleteByMaster = form.Form_Detail_SqlDeleteByMaster,
                    Form_Detail_SqlGetByMaster = form.Form_Detail_SqlGetByMaster,
                    Text = String.Format("Thông tin {0}", form.Form_Name),

                    SourceDataId = Convert.ToInt32(firstList.SourceDataId),
                    ControlName = lookupEdit.Name,
                    DisplayMember = firstList.DisplayMember,
                    ValueMember = firstList.ValueMember,

                    MdiParent = this.MdiParent,
                    WindowState = FormWindowState.Maximized
                };
                frm.Closed += FrmOnClosed;
                frm.Show();
                frm.Focus();
            }
            
        }

        private void FrmOnClosed(object sender, EventArgs eventArgs)
        {
            var frmDynamicDetail = sender as FrmDynamicBase;
            if (frmDynamicDetail == null || !frmDynamicDetail.SaveClose) return;
            //1. Set Again Data Source
            var ctrLookup = GetControlByName(frmDynamicDetail.ControlName) as LookUpEdit;
            if (ctrLookup == null) return;
            DataTable dvLookupEdit = ClsSourceData.GetControlDataBySourceId(frmDynamicDetail.SourceDataId, "");
            ctrLookup.Properties.DataSource = new BindingSource(dvLookupEdit, "");
            ctrLookup.Properties.DisplayMember = frmDynamicDetail.DisplayMember;
            ctrLookup.Properties.ValueMember = frmDynamicDetail.ValueMember;
            //2. Set New ID
            ctrLookup.EditValue = frmDynamicDetail.MasterId;
        }

        private ExpandoObject GetDynamicSqlValue(List<FieldTables> list)
        {
            dynamic ret = new ExpandoObject();
            FieldTables item =
                list.FirstOrDefault(
                    e => e.FieldTableKeyField != null && String.Format("{0}", e.FieldTableKeyField).Length > 0);

            if (item != null)
            {
                string keyField = String.Format("{0}", item.FieldTableKeyField);
                ((IDictionary<String, Object>) ret).Add(keyField, MasterId);
            }
            list = list.Where(op => op.FieldTalbeType != 6 && op.FieldTableReadOnly == false).ToList();

            foreach (FieldTables field in list)
            {
                string controlName = field.FieldTableName;
                if (controlName.Equals(field.FieldTableKeyField)) continue;
                int typeId = Convert.ToInt32(field.FieldTalbeType);

                if (typeId == 1 || typeId == 2)
                {
                    string sret = GetTextValue(controlName, typeId);
                    ((IDictionary<String, Object>) ret).Add(controlName, sret);
                }
                else if (typeId == 3)
                {
                    decimal dret = GetNumberValue(controlName);
                    ((IDictionary<String, Object>) ret).Add(controlName, dret);
                }
                else if (typeId == 4)
                {
                    DateTime? dtret = GetDateValue(controlName);
                    ((IDictionary<String, Object>) ret).Add(controlName, dtret);
                }

                else if (typeId == 5)
                {
                    int? itret = GetLookupValue(controlName);
                    ((IDictionary<String, Object>) ret).Add(controlName, itret);
                }
                else if (typeId == 7) //PictureEdit
                {
                    byte[] btret = GetImageValue(controlName);
                    var deret = new byte[0];

                    ((IDictionary<String, Object>) ret).Add(controlName, btret ?? deret);
                }
                    //CheckEdit
                else if (typeId == 8)
                {
                    bool? ceret = GetCheckEditValue(controlName);
                    ((IDictionary<String, Object>) ret).Add(controlName, ceret ?? false);
                }
                else if (typeId == 9) //ComboEdit
                {
                    string ceret = GetComboEditValue(controlName);
                    ((IDictionary<String, Object>) ret).Add(controlName, ceret);
                }
                else if (typeId == 10) //LookupEdit
                {
                    int? iledit = GetLookupEditValue(controlName);
                    ((IDictionary<String, Object>)ret).Add(controlName, iledit);
                }
                else
                {
                    ((IDictionary<String, Object>) ret).Add(controlName, DBNull.Value);
                }
            }

            return ret;
        }

        private ExpandoObject GetDynamicDetailSqlValue(List<FieldTables> list)
        {
            dynamic ret = new ExpandoObject();
            FieldTables item =
                list.FirstOrDefault(
                    e => e.FieldTableKeyField != null && String.Format("{0}", e.FieldTableKeyField).Length > 0);


            if (item != null)
            {
                string keyField = String.Format("{0}", item.FieldTableKeyField);
                ((IDictionary<String, Object>) ret).Add(keyField, MasterId);
            }
            list = list.Where(op => op.FieldTalbeType == 6).ToList();

            foreach (FieldTables field in list)
            {
                string controlName = field.FieldTableName;
                if (controlName.Equals(field.FieldTableKeyField)) continue;

                DataTable dtret = GetGridValue(controlName);
                ((IDictionary<String, Object>) ret).Add(controlName, dtret);
            }

            return ret;
        }

        private string GetTextValue(string controlName, int typeId)
        {
            string ret = "";
            foreach (Control ctrl in layoutControl.Controls.Cast<Control>().Where(ctrl => ctrl.Name.Equals(controlName))
                )
            {
                ret = typeId == 1
                    ? String.Format("{0}", ((TextEdit) ctrl).EditValue)
                    : (typeId == 2 ? String.Format("{0}", ((MemoEdit) ctrl).EditValue) : "");
            }
            return ret;
        }

        private decimal GetNumberValue(string controlName)
        {
            decimal ret = 0;
            foreach (Control ctrl in layoutControl.Controls.Cast<Control>().Where(ctrl => ctrl.Name.Equals(controlName))
                )
            {
                ret = ((CalcEdit) ctrl).Value;
            }
            return ret;
        }

        private DateTime? GetDateValue(string controlName)
        {
            foreach (Control ctrl in layoutControl.Controls.Cast<Control>().Where(ctrl => ctrl.Name.Equals(controlName))
                )
            {
                return ((DateEdit) ctrl).EditValue == DBNull.Value ? null : (DateTime?) ((DateEdit) ctrl).EditValue;
            }
            return null;
        }

        private bool? GetCheckEditValue(string controlName)
        {
            foreach (Control ctrl in layoutControl.Controls.Cast<Control>().Where(ctrl => ctrl.Name.Equals(controlName))
                )
            {
                return ((CheckEdit) ctrl).Checked;
            }
            return null;
        }

        private string GetComboEditValue(string controlName)
        {
            string ret = "";
            foreach (Control ctrl in layoutControl.Controls.Cast<Control>().Where(ctrl => ctrl.Name.Equals(controlName))
                )
            {
                ret = String.Format("{0}", ((ComboBoxEdit) ctrl).EditValue);
            }
            return ret;
        }

        private int? GetLookupValue(string controlName)
        {
            foreach (Control ctrl in layoutControl.Controls.Cast<Control>().Where(ctrl => ctrl.Name.Equals(controlName))
                )
            {
                return ((SearchLookUpEdit) ctrl).EditValue == DBNull.Value
                    ? null
                    : (int?) ((SearchLookUpEdit) ctrl).EditValue;
            }
            return null;
        }

        private int? GetLookupEditValue(string controlName)
        {
            foreach (Control ctrl in layoutControl.Controls.Cast<Control>().Where(ctrl => ctrl.Name.Equals(controlName))
                )
            {
                return ((LookUpEdit)ctrl).EditValue == DBNull.Value
                    ? null
                    : (int?)((LookUpEdit)ctrl).EditValue;
            }
            return null;
        }

        private byte[] GetImageValue(string controlName)
        {
            return
                layoutControl.Controls.Cast<Control>()
                    .Where(ctrl => ctrl.Name.Equals(controlName))
                    .Select(ctrl => (byte[]) ((PictureEdit) ctrl).EditValue)
                    .FirstOrDefault();
        }

        private DataTable GetGridValue(string controlName)
        {
            foreach (Control ctrl in layoutControl.Controls.Cast<Control>().Where(ctrl => ctrl.Name.Equals(controlName))
                )
            {
                var grdDetail = ctrl as GridControl;
                if (grdDetail != null)
                {
                    grdDetail.EmbeddedNavigator.Buttons.DoClick(grdDetail.EmbeddedNavigator.Buttons.EndEdit);
                    return (DataTable) grdDetail.DataSource;
                }
            }
            return null;
        }

        private Control GetControlByName(string controlName)
        {
            return layoutControl.Controls.Find(controlName, true).FirstOrDefault();
        }

        private void GetDetail()
        {
            var data = new DataTable();
            if (!String.IsNullOrEmpty(Form_Detail_SqlDeleteByMaster))
            {
                Form_Detail_SqlDeleteByMaster = String.Format("{0} WHERE {1}={2}", Form_Detail_SqlDeleteByMaster,
                    Form_TableKeyField, MasterId);
                data = ClsDynamic.GetObject(Form_Detail_SqlDeleteByMaster);
            }
            if (data.Rows.Count > 0)
            {
                DataRow row = data.Rows[0];
                List<FieldTables> listControl = _list.Where(op => op.FieldTableReadOnly == false).ToList();
                foreach (FieldTables field in listControl)
                {
                    string controlName = field.FieldTableName;
                    int typeId = Convert.ToInt32(field.FieldTalbeType);
                    switch (typeId)
                    {
                        case 1: //TextEdit
                            var textEdit = GetControlByName(controlName) as TextEdit;
                            if (textEdit != null) textEdit.EditValue = row[controlName];
                            break;
                        case 2: //Memo Edit
                            var memoEdit = GetControlByName(controlName) as MemoEdit;
                            if (memoEdit != null) memoEdit.EditValue = row[controlName];
                            break;
                        case 3: //CalcEdit
                            var calcEdit = GetControlByName(controlName) as CalcEdit;
                            if (calcEdit != null) calcEdit.EditValue = row[controlName];
                            break;
                        case 4: //DateTime
                            var dateEdit = GetControlByName(controlName) as DateEdit;
                            if (dateEdit != null) dateEdit.EditValue = row[controlName];
                            break;
                        case 5: //Lookup Edit
                            var lookupEdit = GetControlByName(controlName) as SearchLookUpEdit;
                            if (lookupEdit != null) lookupEdit.EditValue = row[controlName];
                            break;
                        case 7: //PictureEdit
                            var pictureEdit = GetControlByName(controlName) as PictureEdit;
                            if (pictureEdit != null) pictureEdit.EditValue = row[controlName];
                            break;
                        case 8: //CheckEdit
                            var checkEdit = GetControlByName(controlName) as CheckEdit;
                            if (checkEdit != null) checkEdit.EditValue = row[controlName];
                            break;
                        case 9: //Combobox
                            var comboBoxEdit = GetControlByName(controlName) as ComboBoxEdit;
                            if (comboBoxEdit != null) comboBoxEdit.EditValue = row[controlName];
                            break;
                        case 10: //LookupEdit
                            var lookupValueEdit = GetControlByName(controlName) as LookUpEdit;
                            if (lookupValueEdit != null) lookupValueEdit.EditValue = row[controlName];
                            break;
                    }
                }
            }
        }

        private void DoSave()
        {
            #region "Check Validate"

            if (!OperateValidate())
            {
                XtraMessageBox.Show("Vui lòng nhập đầy đủ thông tin trước khi lưu", "Thông báo", MessageBoxButtons.OK,
                    MessageBoxIcon.Warning);
                return;
            }

            var listCheckDuplicate = _list.Where(p => p.FieldTableIsCheckDuplicate == true).ToList();
            if (listCheckDuplicate.Count > 0)
            {
                string sql = String.Format("SELECT COUNT(*) FROM {0}", TableName);
                string where = "";
                string message = "";
                foreach (var item in listCheckDuplicate)
                {
                    if (item.FieldTalbeType == 1 || item.FieldTalbeType == 2)
                    {
                        @where = @where.Length == 0
                            ? String.Format(" WHERE {0}='{1}'", item.FieldTableName,
                                GetTextValue(item.FieldTableName, (int) item.FieldTalbeType))
                            : @where + String.Format(" AND {0}='{1}'", item.FieldTableName,
                                GetTextValue(item.FieldTableName, (int) item.FieldTalbeType));
                    }
                    else if (item.FieldTalbeType == 5)
                    {
                        @where = @where.Length == 0
                            ? String.Format(" WHERE {0}={1}", item.FieldTableName,
                                GetLookupValue(item.FieldTableName))
                            : @where + String.Format(" AND {0}='{1}'", item.FieldTableName,
                                GetLookupValue(item.FieldTableName));
                    }

                    message = message.Length == 0
                            ? item.FieldTableDescription
                            : message + item.FieldTableDescription;
                }
                sql = sql + where;
                if (MasterId > 0) sql = String.Format("{0} AND {1}<>{2}", sql, Form_TableKeyField, MasterId);
               
                int count = ClsDynamic.GetCountObject(sql);
                if (count > 0)
                {
                    XtraMessageBox.Show(string.Format("{0} không được phép trùng.", message), "Thông báo", MessageBoxButtons.OK,
                                    MessageBoxIcon.Warning);
                    return;
                }
            }
            #endregion

            dynamic data = GetDynamicSqlValue(_list);
            dynamic dataDetail = GetDynamicDetailSqlValue(_list);
            Entity.Forms form = ClsForms.SelectByPk(FormNo);
            try
            {
                if (MasterId > 0)
                {
                    if (form.Form_IsBusiness == true)
                    {
                        ((IDictionary<String, Object>) data).Add("UpdateBy", ClsVariable.EmployeeId);
                        ((IDictionary<String, Object>) data).Add("UpdateDate", DateTime.Now);
                    }
                    
                    ClsDynamic.UpdateObject(TableName, Form_TableKeyField, data, dataDetail, _listGrid, FormNo);
                }
                else
                {
                    if (form.Form_IsBusiness == true)
                    {
                        ((IDictionary<String, Object>) data).Add("FormId", FormNo);
                        ((IDictionary<String, Object>) data).Add("VoucherCate", VoucherCate);

                        ((IDictionary<String, Object>) data).Add("CreateBy", ClsVariable.EmployeeId);
                        ((IDictionary<String, Object>) data).Add("CreateDate", DateTime.Now);
                    }
                    var listAuto = _list.FirstOrDefault(p => p.FieldTableIsAutoNumber == true);
                    string fieldNameAutoNumber = "";
                    if (listAuto != null) fieldNameAutoNumber = listAuto.FieldTableName;

                    ClsDynamic.InsertObject(TableName, Form_TableKeyField, data, dataDetail, _listGrid, FormNo, fieldNameAutoNumber);
                    var value = ((IDictionary<String, Object>)data)[Form_TableKeyField];
                    if (value != null) MasterId = Convert.ToInt32(value);
                }
                if (SaveNew)
                {
                    MasterId = 0;
                    BlankForm();
                }
                else if (SaveClose)
                {
                    Close();
                }
            }
            catch (Exception exception)
            {
                MessageBox.Show(exception.Message);
            }
        }

        private void DoDelete()
        {
            dynamic data = new ExpandoObject();
            ((IDictionary<String, Object>) data).Add(Form_TableKeyField, MasterId);
            try
            {
                ClsDynamic.DeleteObject(Form_TableName, Form_TableKeyField, data, FormNo);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        #endregion

        #region "PostFix"

        public static int GetPriority(string op)
        {
            if (op == "*" || op == "/" || op == "%")
                return 2;
            if (op == "+" || op == "-")
                return 1;
            return 0;
        }

        public static void FormatExpression(ref string expression)
        {
            expression = expression.Replace(" ", "");
            expression = Regex.Replace(expression, @"\+|\-|\*|\/|\%|\^|\)|\(",
                delegate(Match match) { return " " + match.Value + " "; });
            expression = expression.Replace("  ", " ");
            expression = expression.Trim();
        }

        private static bool IsOperator(string str)
        {
            return Regex.Match(str, @"\+|\-|\*|\/|\%").Success;
        }

        public static bool IsOperand(string str)
        {
            return Regex.Match(str, @"^\d+$|([a-z]|[A-Z])$").Success;
            // return Regex.Match(str, @"([a-z]|[A-Z])$").Success;
        }

        public static string Infix2Postfix(string infix)
        {
            FormatExpression(ref infix);
            IEnumerable<string> str = infix.Split(' ');
            var stack = new Stack<string>();
            var postfix = new StringBuilder();
            foreach (string s in str)
            {
                if (IsOperand(s))
                    postfix.Append(s).Append(" ");
                else if (s == "(")
                    stack.Push(s);
                else if (s == ")")
                {
                    string x = stack.Pop();
                    while (x != "(")
                    {
                        postfix.Append(x).Append(" ");
                        x = stack.Pop();
                    }
                }
                else // IsOperator(s)
                {
                    while (stack.Count > 0 && GetPriority(s) <= GetPriority(stack.Peek()))
                        postfix.Append(stack.Pop()).Append(" ");
                    stack.Push(s);
                }
            }
            while (stack.Count > 0)
                postfix.Append(stack.Pop()).Append(" ");
            return postfix.ToString();
        }

        public void EvaluatePostfix(string postfix, string fieldName, GridView view, string currentFieldName,
            object currentValue)
        {
            var stack = new Stack<decimal>();
            postfix = postfix.Trim();
            IEnumerable<string> enumer = postfix.Split(' ');
            foreach (string s in enumer)
            {
                if (IsOperand(s))
                {
                    decimal num;
                    if (decimal.TryParse(s, out num))
                    {
                        stack.Push(decimal.Parse(s));
                    }
                    else
                    {
                        string fName = s;
                        if (!String.IsNullOrEmpty(fName))
                        {
                            decimal value;
                            if (fName.Equals(currentFieldName))
                            {
                                value = Convert.ToDecimal(currentValue);
                            }
                            else
                            {
                                Control ctrl = GetControlByName(fName);
                                if (ctrl != null)
                                {
                                    value = GetNumberValue(fName);
                                }
                                else
                                {
                                    if (view.GetRowCellValue(view.FocusedRowHandle, fName) == null
                                    || view.GetRowCellValue(view.FocusedRowHandle, fName) == DBNull.Value)
                                    {
                                        value = 0;
                                    }
                                    else
                                    {
                                        value = Convert.ToDecimal(view.GetRowCellValue(view.FocusedRowHandle, fName));
                                    }
                                }
                                
                            }

                            stack.Push(value);
                        }
                    }
                }
                else
                {
                    decimal x = stack.Pop();
                    decimal y = stack.Pop();
                    switch (s)
                    {
                        case "+":
                            y += x;
                            break;
                        case "-":
                            y -= x;
                            break;
                        case "*":
                            y *= x;
                            break;
                        case "/":
                            y /= x;
                            break;
                        case "%":
                            y %= x;
                            break;
                    }
                    stack.Push(y);
                }
            }
            decimal ret = stack.Pop();

            view.SetRowCellValue(view.FocusedRowHandle, fieldName, ret);
        }

        public void EvaluatePostfix(string postfix, string fieldName, string currentFieldName, object currentValue)
        {
            var stack = new Stack<decimal>();
            postfix = postfix.Trim();
            IEnumerable<string> enumer = postfix.Split(' ');
            foreach (string s in enumer)
            {
                if (IsOperand(s))
                {
                    decimal num;
                    if (decimal.TryParse(s, out num))
                    {
                        stack.Push(decimal.Parse(s));
                    }
                    else
                    {
                        string fName = s;
                        if (!String.IsNullOrEmpty(fName))
                        {
                            decimal value = fName.Equals(currentFieldName)
                                ? Convert.ToDecimal(currentValue)
                                : GetNumberValue(fName);
                            stack.Push(value);
                        }
                    }
                }
                else
                {
                    decimal x = stack.Pop();
                    decimal y = stack.Pop();
                    switch (s)
                    {
                        case "+":
                            y += x;
                            break;
                        case "-":
                            y -= x;
                            break;
                        case "*":
                            y *= x;
                            break;
                        case "/":
                            y /= x;
                            break;
                        case "%":
                            y %= x;
                            break;
                    }
                    stack.Push(y);
                }
            }
            decimal ret = stack.Pop();
            var calcEdit = GetControlByName(fieldName) as CalcEdit;
            if (calcEdit != null) calcEdit.EditValue = ret;
        }

        public void EvaluateConcatPostfix(string postfix, string fieldName, string currentFieldName, object currentValue)
        {
            var stack = new Stack<string>();
            postfix = postfix.Trim();
            IEnumerable<string> enumer = postfix.Split(' ');
            foreach (string s in enumer)
            {
                if (IsOperand(s))
                {
                    string fName = s;
                    if (!String.IsNullOrEmpty(fName))
                    {
                        string value = fName.Equals(currentFieldName)
                            ? String.Format("{0}", currentValue)
                            : GetTextValue(fName, 1);
                        stack.Push(value);
                    }
                }
                else
                {
                    string x = stack.Pop();
                    string y = stack.Pop();
                    switch (s)
                    {
                        case "+":
                            y = String.Format("{0} {1}", y, x);
                            break;
                        case "-":
                            y = String.Format("{0} - {1}", y, x);
                            break;
                        case "*":
                            y = String.Format("{0} * {1}", y, x);
                            break;
                        case "/":
                            y = String.Format("{0} / {1}", y, x);
                            break;
                        case "%":
                            y = String.Format("{0} {1}", y, x);
                            break;
                    }
                    stack.Push(y);
                }
            }
            string ret = stack.Pop();
            var calcEdit = GetControlByName(fieldName) as TextEdit;
            if (calcEdit != null) calcEdit.EditValue = ret;
        }

        #endregion

        #region "Validate"

        private List<ControlRule> GetRuleList()
        {
            var rulelist = new List<ControlRule>();
            List<FieldTables> listControlRule =
                _list.Where(op => op.FieldTalbeType != 6 && op.FieldTalbeIsValidate == true).ToList();
            foreach (FieldTables rule in listControlRule)
            {
                Control ctr = GetControlByName(rule.FieldTableName);
                //Not Emptype
                if (rule.FieldTableValidateType == 1)
                {
                    rulelist.Add(new ControlRule(ctr, ControlRule.NotEmpty()));
                }
                    //GreateOrEqual Number
                else if (rule.FieldTableValidateType == 2)
                {
                    rulelist.Add(new ControlRule(ctr,
                        ControlRule.NoLessNumber(Convert.ToDecimal(rule.FieldTableValidateToNumber))));
                }
                    //Greate Number
                else if (rule.FieldTableValidateType == 3)
                {
                    rulelist.Add(new ControlRule(ctr,
                        ControlRule.GreaterNumber(Convert.ToDecimal(rule.FieldTableValidateFromNumber))));
                }
                    //Between Number
                else if (rule.FieldTableValidateType == 4)
                {
                    rulelist.Add(new ControlRule(ctr,
                        ControlRule.BetweenNumbers(Convert.ToDecimal(rule.FieldTableValidateFromNumber),
                            Convert.ToDecimal(rule.FieldTableValidateToNumber))));
                }
                    //between Date
                else if (rule.FieldTableValidateType == 5)
                {
                    DateTime from = Convert.ToDateTime(rule.FieldTableValidateFromDate);
                    DateTime to = Convert.ToDateTime(rule.FieldTableValidateToDate);
                    rulelist.Add(new ControlRule(ctr, ControlRule.BetweenDate(from, to)));
                }
            }

            return rulelist;
        }

        private bool OperateValidate()
        {
            bool flag = true;
            _myvalidation.RuleList = GetRuleList();
            if (!_myvalidation.Validate())
            {
                flag = false;
            }
            return flag;
        }

        #endregion

        #region "Form Event"

        private void FrmDynamicBaseLoad(object sender, EventArgs e)
        {
            CreateLayoutForms();
            BlankForm();
            if (!String.IsNullOrEmpty(FormXtraLayoutTemplate))
            {
                string fileLayout = ClsVariable.GetRestoreLayoutFullPath(FormXtraLayoutTemplate);
                layoutControl.RestoreLayoutFromXml(fileLayout);
            }
            if (MasterId > 0) GetDetail();
            btnSaveNew.Enabled = !OnlyView;
            btnSave.Enabled = !OnlyView;
            btnSaveClose.Enabled = !OnlyView;
            btnDelete.Enabled = !OnlyView;
            btnDesign.Enabled = !OnlyView;
        }

        #endregion

        #region "Toolbar Event"

        private void TbMenuItemClick(object sender, ItemClickEventArgs e)
        {
            switch (e.Item.Name)
            {
                case "btnSave":
                    DoSave();
                    break;
                case "btnSaveNew": //Lưu và thêm mới
                    SaveNew = true;
                    SaveClose = false;
                    DoSave();
                    break;
                case "btnSaveClose": //Lưu và đóng
                    SaveClose = true;
                    SaveNew = false;
                    DoSave();
                    break;
                case "btnDelete":
                    DoDelete();
                    break;
                case "btnDesign":
                    ClsVariable.ShowDesignXtraGrid(ListGridControl[GridNo]);
                    break;
                case "btnRefresh": //Nạp lại danh mục
                    break;
                case "btnHistory": //History
                    break;
                case "btnClose":
                    Close();
                    break;
            }
        }

        #endregion

        #region "Lookup Event"

        private void slupDropDown_EditValueChanged(object sender, EventArgs e)
        {
            var lookup = sender as SearchLookUpEdit;
            if (lookup == null) return;
            var dataSource = lookup.Properties.DataSource as DataTable;
            if (dataSource == null) return;
            DataView dvSource = dataSource.DefaultView;
            short id = Convert.ToInt16(lookup.EditValue);

            #region "Get Data Master Form Object"
            List<FieldTables> listControl =
                _list.Where(p => p.ParentValueMember.Equals(lookup.Name) && p.FieldTalbeType != 6).ToList();
            foreach (FieldTables item in listControl)
            {
                Control ctr = layoutControl.Controls.Find(item.FieldTableName, true).FirstOrDefault();
                var textEdit = ctr as TextEdit;
                var dateEdit = ctr as DateEdit;
                var memoEdit = ctr as MemoEdit;
                var calcEdit = ctr as CalcEdit;
                var searchLookUpEdit = ctr as SearchLookUpEdit;
                //Neu la search lookup thi ta bind lai du lieu cho dieu khien
                if (searchLookUpEdit != null)
                {
                    FieldTables listSearch =
                        _list.FirstOrDefault(
                            op => op.FieldTableName == searchLookUpEdit.Name && op.FormNo == FormNo);
                    if (listSearch != null)
                    {
                        string where = String.Format(" WHERE {0}={1}", lookup.Properties.ValueMember, id);
                        DataTable dtLookup = ClsSourceData.GetControlDataBySourceId(listSearch.SourceDataId, @where);
                        ((SearchLookUpEdit) ctr).Properties.DataSource = dtLookup;
                        ((SearchLookUpEdit) ctr).Properties.ValueMember = listSearch.ValueMember;
                        ((SearchLookUpEdit) ctr).Properties.DisplayMember = listSearch.DisplayMember;
                    }
                }
                else
                {
                    //Get data source
                    dvSource.RowFilter = String.Format("{0}={1}", lookup.Properties.ValueMember, id);
                    object value = null;
                    if (dvSource.Count > 0)
                    {
                        value = dvSource[0][item.FieldTableName];
                    }
                    if (textEdit != null)
                        ((TextEdit) ctr).EditValue = value;
                    if (dateEdit != null)
                        ((DateEdit) ctr).EditValue = value;
                    if (memoEdit != null)
                        ((MemoEdit) ctr).EditValue = value;
                    if (calcEdit != null)
                        ((CalcEdit) ctr).EditValue = value;
                }

                dvSource.RowFilter = "";
            }

            #endregion

            #region "Get Data for Lookup on Grid"

            FieldTables fieldTableId =
                _list.FirstOrDefault(
                    o => o.ParentValueMember == lookup.Name && o.FormNo == FormNo && o.FieldTalbeType == 6);
            if (fieldTableId != null)
            {
                List<FieldTableDetails> listDetails = ClsFieldTables.SelectDetails(fieldTableId.FieldTableId);
                foreach (FieldTableDetails detail in listDetails)
                {
                    string controlName = String.Format("RepositoryItemSearchLookUpEdit{0}{1}",
                        fieldTableId.FieldTableName, detail.FieldTableDetailColumnName);
                    RepositoryItemSearchLookUpEdit lookupCtr =
                        ListSearchLookupEdit.FirstOrDefault(p => p.Name == controlName);
                    string where = String.Format(" WHERE {0}={1}", lookup.Properties.ValueMember, id);
                    DataTable dvLookup = ClsSourceData.GetControlDataBySourceId(detail.SourceDataId, @where);
                    if (lookupCtr == null) continue;
                    lookupCtr.DataSource = dvLookup;
                    lookupCtr.DisplayMember = detail.DisplayMember;
                    lookupCtr.ValueMember = detail.ValueMember;
                }
            }

            #endregion
        }

        private void repositoryItemSpinEdit1_EditValueChanged(object sender, EventArgs e)
        {
            var lookUp = (SpinEdit) sender;
            if (lookUp.EditValue != null)
            {
                GridNo = Convert.ToInt32(lookUp.EditValue);
            }
        }

        private void txtCalcEdit_EditValueChanged(object sender, EventArgs e)
        {
            var calEdit = (CalcEdit) sender;
            List<FieldTables> listControl =
                _list.Where(p => p.FieldTalbeType == 3 && p.FieldTableFormula.Length > 0).ToList();
            foreach (FieldTables field in listControl)
            {
                string expression = field.FieldTableFormula;
                string postFix = Infix2Postfix(expression);
                EvaluatePostfix(postFix, field.FieldTableName, calEdit.Name, calEdit.Value);
            }
        }

        private void txtTextEdit_EditValueChanged(object sender, EventArgs e)
        {
            var textEdit = (TextEdit) sender;
            List<FieldTables> listControl =
                _list.Where(p => p.FieldTalbeType == 1 && p.FieldTableFormula.Length > 0).ToList();
            foreach (FieldTables field in listControl)
            {
                string expression = field.FieldTableFormula;
                string postFix = Infix2Postfix(expression);
                EvaluateConcatPostfix(postFix, field.FieldTableName, textEdit.Name, textEdit.Text);
            }
        }

        #endregion

        #region "Grid Event"

        private void gridStatusGridView_CellValueChanged(object sender, CellValueChangedEventArgs e)
        {
            if (e.Value == null) return;
            var gridView = sender as GridView;
            if (gridView == null) return;
            string controlName = gridView.GridControl.Name;
            FieldTables list = gridView.Tag != null
                ? (FieldTables) gridView.Tag
                : _list.FirstOrDefault(op => op.FieldTableName == controlName && op.FormNo == FormNo);

            if (list == null) return;
            string[] arrListField = list.GridLayoutFieldWith.Split(',');
            string[] arrListFieldLookup = list.FieldTableListLookupChange.Split(',');
            string[] arrListFieldWhere = list.FieldTableListWhereField.Split(',');
            
            _listFieldNumberHasEvent.AddRange(arrListField);
            _listFieldLookupHasEvent.AddRange(arrListFieldLookup);
            _listFieldWhere.AddRange(arrListFieldWhere);

            if (_listFieldNumberHasEvent.Contains(e.Column.FieldName))
            {
                List<FieldTableDetails> listDetail = ClsFieldTables.SelectFormulaColumn(list.FieldTableId);
                //Duyệt tất cả các cột công thức có liên quan 
                foreach (FieldTableDetails item in listDetail)
                {
                    string expression = item.FieldTableDetailFormula;
                    string postFix = Infix2Postfix(expression);
                    EvaluatePostfix(postFix, item.FieldTableDetailColumnName, gridView, e.Column.FieldName, e.Value);
                }
            }
            //Lay tat ca nhung cot cua Grid co loai =6 (Lookup) cua Grid hien tai
            if (arrListFieldLookup.Contains(e.Column.FieldName))
            {
                List<FieldTableDetails> listLookup = ClsFieldTables.SelectDetails(list.FieldTableId);
                foreach (FieldTableDetails lookup in listLookup)
                {
                    //Lay data source cua loai = 6
                    string where = String.Format(" WHERE {0}={1}", e.Column.FieldName, e.Value);
                    DataTable dataSource = ClsSourceData.GetControlDataBySourceId(lookup.SourceDataId, @where);
                    if (dataSource == null || dataSource.Rows.Count <= 0) continue;
                    DataRow row = dataSource.Rows[0];
                    //Lay tat ca cac cot lien quan co parent = FieldName
                    List<FieldTableDetails> listColumn = ClsFieldTables.SelectDetails(list.FieldTableId,
                        lookup.FieldTableDetailColumnName);

                    foreach (FieldTableDetails column in listColumn)
                    {
                        gridView.SetRowCellValue(e.RowHandle, column.FieldTableDetailColumnName,
                            row[column.FieldTableDetailColumnName]);
                    }
                }
            }
            //Lay tat ca cac cot lay dieu kien
            if (arrListFieldWhere.Contains(e.Column.FieldName))
            {
                var listWhere = ClsFieldTables.SelectDetails(list.FieldTableId).Where(p => p.FieldTableListWhereField!=null && 
                    p.FieldTableListWhereField.Contains(e.Column.FieldName)).ToList();
                string whereField = list.FieldTableListWhereField;
                foreach (var item in listWhere)
                {
                    int sourceDataWhere = Convert.ToInt32(item.SourceDataIdWhere);
                    string sourceData = ClsSourceData.SelectByPk(sourceDataWhere).SourceDataValue;//Nguon du lieu dieu kien
                    string fieldSet = item.FieldTableGetWhereField;//Gan gia tri cho cot
                    SetColumnFieldWhere(whereField, sourceData, e.Column.FieldName, e.Value, gridView, fieldSet);
                }
            }
            
        }

        public void SetColumnFieldWhere(string whereField,
            string sourceData,
            string currentField,
            object currentValue,
            GridView grvDynamic,
            string fieldSet)
        {
            var columnType = grvDynamic.Columns[currentField].ColumnType;
            var arrMsg = whereField.Split(',');
            for (int i = 0; i < arrMsg.Length; i++)
            {
                string msg = arrMsg[i];
                string msgResource;
                if (columnType.Name.Contains("Date"))
                {
                    msgResource = msg.Equals(currentField) ?
                    Convert.ToDateTime(currentValue).ToString("dd MMM yyyy") :
                    Convert.ToDateTime(grvDynamic.GetRowCellValue(grvDynamic.FocusedRowHandle, msg)).ToString("dd MMM yyyy");
                }
                else
                {
                    msgResource = msg.Equals(currentField) ?
                    Convert.ToString(currentValue) :
                    String.Format("{0}", grvDynamic.GetRowCellValue(grvDynamic.FocusedRowHandle, msg));
                }
                msgResource = String.IsNullOrEmpty(msgResource) ? "0" : msgResource;
                sourceData = sourceData.Replace("{" + i + "}", msgResource);
            }
            DataTable dtRet = ClsDynamic.GetObject(sourceData);
            if (dtRet != null && dtRet.Rows.Count > 0)
            {
                var row = dtRet.Rows[0];
                grvDynamic.SetRowCellValue(grvDynamic.FocusedRowHandle, fieldSet, row[fieldSet]);
            }
        }
        #endregion
    }
}